1 /** 2 * A flat image storage type. 3 * Useful for your underlying contextual needs. 4 * 5 * License: 6 * Copyright Devisualization (Richard Andrew Cattermole) 2014 - 2017. 7 * Distributed under the Boost Software License, Version 1.0. 8 * (See accompanying file LICENSE_1_0.txt or copy at 9 * http://www.boost.org/LICENSE_1_0.txt) 10 */ 11 module devisualization.image.storage.flat; 12 import std.experimental.color : isColor; 13 import stdx.allocator : IAllocator, theAllocator; 14 15 /** 16 * Represents an image using a flat array. 17 * 18 * Because the usage of multiplication is required to index and assign, 19 * it is not recommend to be used outside of drawing contexts. 20 * Where this is the least expensive option for a buffer to draw upon. 21 * 22 * Will automatically deallocate its memory when it goes out of scope. 23 * Should not be copied or moved around. 24 * 25 * See_Also: 26 * ImageStorage 27 */ 28 struct FlatImageStorage(Color) if (isColor!Color) { 29 private { 30 size_t width_, height_; 31 IAllocator allocator; 32 Color[] data; 33 } 34 35 /// 36 this(size_t width, size_t height, IAllocator allocator = theAllocator()) @trusted { 37 import stdx.allocator : makeArray; 38 this.allocator = allocator; 39 40 width_ = width; 41 height_ = height; 42 43 data = allocator.makeArray!(Color)(width * height); 44 } 45 46 ~this() @trusted { 47 import stdx.allocator : dispose; 48 49 if (!__ctfe && data !is null) 50 allocator.dispose(data); 51 } 52 53 @property { 54 /// 55 size_t width() @nogc nothrow @safe { return width_; } 56 57 /// 58 size_t height() @nogc nothrow @safe { return height_; } 59 } 60 61 /// 62 Color getPixel(size_t x, size_t y) @nogc @safe { return data[(y * width) + x]; } 63 64 /// 65 void setPixel(size_t x, size_t y, Color value) @nogc @safe { data[(y * width) + x] = value; } 66 67 /// 68 Color opIndex(size_t x, size_t y) @nogc @safe{ return getPixel(x, y); } 69 70 /// 71 void opIndexAssign(Color value, size_t x, size_t y) @nogc @safe { setPixel(x, y, value); } 72 73 /// 74 bool resize(size_t newWidth, size_t newHeight) @trusted { 75 import stdx.allocator : dispose, makeArray; 76 import std.algorithm : min; 77 78 scope(failure) 79 return false; 80 81 Color[] newData; 82 83 if (newWidth == 0 || newHeight == 0) { 84 } else { 85 newData = allocator.makeArray!(Color)(newWidth * newHeight); 86 87 size_t minWidth = min(width, newWidth); 88 size_t offsetOld, offsetNew; 89 foreach(y; 0 .. min(height, newHeight)) { 90 newData[offsetNew .. offsetNew + minWidth] = data[offsetOld .. offsetOld + minWidth]; 91 92 offsetOld += width; 93 offsetNew += newWidth; 94 } 95 96 } 97 98 allocator.dispose(data); 99 100 width_ = newWidth; 101 height_ = newHeight; 102 data = newData; 103 104 return true; 105 } 106 107 /** 108 * Get the array that backs this image storage type 109 * 110 * This is considered an unsafe operation. 111 * Do not use unless you know what you are doing. 112 * 113 * Returns: 114 * The backing array containing the pixels 115 */ 116 immutable(Color[]) __pixelsRawArray() { 117 return cast(immutable)data; 118 } 119 }